/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>

#include <imu/imu.h>
#include <ipmb/ipmb.h>
#include <mc/engine/service.h>
#include <mc/variant.h>

#include <memory>
#include <stdexcept>
#include <string>
#include <vector>

namespace {

mc::variant make_ipmi_variant(int completion_code, const std::vector<uint8_t>& data) {
    mc::variants payload;
    for (auto byte : data) {
        payload.push_back(static_cast<int64_t>(byte));
    }

    mc::variants result;
    result.push_back(static_cast<int64_t>(completion_code));
    result.push_back(mc::variant(payload));
    return mc::variant(result);
}

mc::variant make_failure_variant(int completion_code) {
    mc::variants empty_payload;
    mc::variants result;
    result.push_back(static_cast<int64_t>(completion_code));
    result.push_back(mc::variant(empty_payload));
    return mc::variant(result);
}

class imu_test : public ::testing::Test {
protected:
    void SetUp() override {
        m_service = std::make_unique<mc::engine::service>("bmc.kepler.test_imu");
        m_imu     = std::make_unique<dev::imu>(m_service.get());
    }

    void TearDown() override {
        m_imu.reset();
        m_service.reset();
    }

    std::unique_ptr<mc::engine::service> m_service;
    std::unique_ptr<dev::imu>            m_imu;
};

} // namespace

TEST_F(imu_test, constructor_requires_service) {
    EXPECT_NE(m_imu, nullptr);
    EXPECT_THROW(dev::imu(nullptr), mc::invalid_argument_exception);
}



TEST_F(imu_test, parse_pmu_pci_response_basic) {
    std::vector<uint8_t> payload = {0xDB, 0x07, 0x00, 0x11, 0x22, 0x33, 0x44};

    auto parsed = m_imu->parse_pmu_pci_response(payload, 4);

    EXPECT_EQ(parsed, (std::vector<uint8_t>{0x11, 0x22, 0x33, 0x44}));
}

TEST_F(imu_test, parse_pmu_pci_response_handles_short_data) {
    std::vector<uint8_t> payload = {0xDB, 0x07, 0x00, 0x55};
    auto                 parsed  = m_imu->parse_pmu_pci_response(payload, 4);
    EXPECT_EQ(parsed, (std::vector<uint8_t>{0x55}));
}

TEST_F(imu_test, parse_pmu_pci_response_empty_guard) {
    std::vector<uint8_t> empty_payload;
    auto                 parsed = m_imu->parse_pmu_pci_response(empty_payload, 4);
    EXPECT_TRUE(parsed.empty());
}

TEST_F(imu_test, parse_pmu_pci_response_header_too_short) {
    std::vector<uint8_t> payload = {0xAA, 0xBB};
    auto                 parsed  = m_imu->parse_pmu_pci_response(payload, 2);
    EXPECT_TRUE(parsed.empty());
}


TEST_F(imu_test, send_ipmi_request_invalid_input) {
    std::string response;
    EXPECT_FALSE(m_imu->send_ipmi_request(nullptr, 0, response));
}
